<!DOCTYPE html>
<html prefix="og: http://ogp.me/ns# article: http://ogp.me/ns/article#
" lang="zh_cn">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>自动生成类实现接口 | vitamind3 竹里馆</title>
<link href="../../assets/css/all-nocdn.css" rel="stylesheet" type="text/css">
<link href="../../assets/css/ipython.min.css" rel="stylesheet" type="text/css">
<link href="../../assets/css/nikola_ipython.css" rel="stylesheet" type="text/css">
<meta name="theme-color" content="#5670d4">
<meta name="generator" content="Nikola (getnikola.com)">
<link rel="alternate" type="application/rss+xml" title="RSS" hreflang="zh_cn" href="../../rss.xml">
<link rel="canonical" href="https://vitamind3.gitee.io/posts/zi-dong-sheng-cheng-lei-shi-xian-jie-kou/">
<!--[if lt IE 9]><script src="../../assets/js/html5.js"></script><![endif]--><meta name="author" content="vitamind3">
<link rel="prev" href="../tui-jian-fodyku/" title="推荐fody库" type="text/html">
<link rel="next" href="../tui-jian-qi-yong-cte-xing-nullable-reference-types/" title="推荐启用C#特性Nullable reference types" type="text/html">
<meta property="og:site_name" content="vitamind3 竹里馆">
<meta property="og:title" content="自动生成类实现接口">
<meta property="og:url" content="https://vitamind3.gitee.io/posts/zi-dong-sheng-cheng-lei-shi-xian-jie-kou/">
<meta property="og:description" content="最近在一个 C# .net 6 项目里实现了一个功能，即自动生成类实现接口。


主程序需要从目录中加载一些插件dll，插件dll中会实现接口 IPluginSerivce ，接口提供插件的功能。
主程序在加载了插件 PluginA 后需要有一个类 PluginAProxy 实现接口 IPluginSerivce ， PluginAProxy 调用插件 PluginA 的接口 IPluginSer">
<meta property="og:type" content="article">
<meta property="article:published_time" content="2022-03-29T23:52:08+08:00">
<meta property="article:tag" content=".net">
<meta property="article:tag" content="C#">
<meta property="article:tag" content="nuget">
</head>
<body>
<a href="#content" class="sr-only sr-only-focusable">跳到主内容</a>

<!-- Menubar -->

<nav class="navbar navbar-expand-md static-top mb-4
navbar-dark
bg-dark
"><div class="container">
<!-- This keeps the margins nice -->
        <a class="navbar-brand" href="../../">

            <span id="blog-title">vitamind3 竹里馆</span>
        </a>
        <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#bs-navbar" aria-controls="bs-navbar" aria-expanded="false" aria-label="Toggle navigation">
            <span class="navbar-toggler-icon"></span>
        </button>

        <div class="collapse navbar-collapse" id="bs-navbar">
            <ul class="navbar-nav mr-auto">
<li class="nav-item">
<a href="../../pages/introduction" class="nav-link">欢迎</a>
                </li>
<li class="nav-item">
<a href="../../archive.html" class="nav-link">文章归档</a>
                </li>
<li class="nav-item">
<a href="../../categories/" class="nav-link">分类</a>
                </li>
<li class="nav-item">
<a href="../../rss.xml" class="nav-link">RSS 源</a>

                
            </li>
</ul>
<ul class="navbar-nav navbar-right"></ul>
</div>
<!-- /.navbar-collapse -->
    </div>
<!-- /.container -->
</nav><!-- End of Menubar --><div class="container" id="content" role="main">
    <div class="body-content">
        <!--Body content-->
        
        
        
<article class="post-text h-entry hentry postpage" itemscope="itemscope" itemtype="http://schema.org/Article"><header><h1 class="p-name entry-title" itemprop="headline name"><a href="." class="u-url">自动生成类实现接口</a></h1>

        <div class="metadata">
            <p class="byline author vcard p-author h-card"><span class="byline-name fn p-name" itemprop="author">
                    vitamind3
            </span></p>
            <p class="dateline">
            <a href="." rel="bookmark">
            <time class="published dt-published" datetime="2022-03-29T23:52:08+08:00" itemprop="datePublished" title="2022-03-29 23:52">2022-03-29 23:52</time></a>
            </p>
            

        </div>
        

    </header><div class="e-content entry-content" itemprop="articleBody text">
    <div>
<p>最近在一个 C# .net 6 项目里实现了一个功能，即自动生成类实现接口。</p>
<!-- TEASER_END -->

<p>主程序需要从目录中加载一些插件dll，插件dll中会实现接口 <code>IPluginSerivce</code> ，接口提供插件的功能。
主程序在加载了插件 PluginA 后需要有一个类 PluginAProxy 实现接口 <code>IPluginSerivce</code> ， PluginAProxy 调用插件 PluginA 的接口 <code>IPluginSerivce</code> 。 PluginAProxy 中会根据一些配置信息添加一些额外的处理。</p>
<p>当然可以手工实现 PluginAProxy 类，但我希望能自动化的完成，最终也实现了。方案就是使用 Emit 生成 IL , 同时使用 <code>Castle.DynamicProxy</code> 动态实现接口。</p>
<p>动态实现接口调用 <code>CreateInterfaceProxyWithoutTarget&lt;&gt;()</code> 即可，没啥难度。唯一遇到麻烦的是异步方法：我的接口 <code>IPluginSerivce</code> 中有部分方法返回 Task 类型，这时就需要做一点点特殊处理。</p>
<p>有一个库 <code>Castle.Core.AsyncInterceptor</code> 对Castle.DynamicProxy处理异步方法提供了一些帮助，但是并没有包括 <code>CreateInterfaceProxyWithoutTarget()</code> 。所以还是得自己撸了点代码。主要思路就是判断返回值的类型，生成新的任务。Task类型容易处理，Task&lt;&gt;类型因为涉及返回值，需要处理好 <code>invocation.ReturnValue</code> 。</p>
<!--

Core/dynamicproxy-async-interception.md at master · castleproject/Core (github.com)
https://github.com/castleproject/Core/blob/master/docs/dynamicproxy-async-interception.md#:~:text=DynamicProxy%20requires%20that%20interceptors%20%28or%20the%20proxy%20target,intercepted%20invocation%27s%20return%20value%20prior%20to%20any%20await.
对于异步有返回值的，处理起来有点复杂，没看懂。

Castle DynamicProxy基本用法（AOP） - 拓荒者-NET - 博客园 (cnblogs.com)
https://www.cnblogs.com/youring2/p/10962573.html

这里说到有 Castle.Core.AsyncInterceptor

-->
</div>
    </div>
    <aside class="postpromonav"><nav><ul itemprop="keywords" class="tags">
<li><a class="tag p-category" href="../../categories/net/" rel="tag">.net</a></li>
            <li><a class="tag p-category" href="../../categories/c/" rel="tag">C#</a></li>
            <li><a class="tag p-category" href="../../categories/nuget/" rel="tag">nuget</a></li>
        </ul>
<ul class="pager hidden-print">
<li class="previous">
                <a href="../tui-jian-fodyku/" rel="prev" title="推荐fody库">上一篇文章</a>
            </li>
            <li class="next">
                <a href="../tui-jian-qi-yong-cte-xing-nullable-reference-types/" rel="next" title="推荐启用C#特性Nullable reference types">下一篇文章</a>
            </li>
        </ul></nav></aside></article><!--End of body content--><footer id="footer">
            Contents ©         <a href="https://vitamind3.gitee.io/">vitamind3</a> - Powered by         <a href="https://getnikola.com" rel="nofollow">Nikola</a>         
            
            
        </footer>
</div>
</div>


        <script src="../../assets/js/all-nocdn.js"></script><script>
    baguetteBox.run('div#content', {
        ignoreClass: 'islink',
        captions: function(element){var i=element.getElementsByTagName('img')[0];return i===undefined?'':i.alt;}});
    </script><script>
var _hmt = _hmt || [];
(function() {
  var hm = document.createElement("script");
  hm.src = "https://hm.baidu.com/hm.js?09027755f7478e129aec2cdd3acf9a4c";
  var s = document.getElementsByTagName("script")[0]; 
  s.parentNode.insertBefore(hm, s);
})();
</script>
</body>
</html>
